package ch.mobi.osgi2maven2;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;

import com.google.code.mjl.Log;
import com.google.code.mjl.LogFactory;
import com.google.code.mjl.LogManager;
import com.springsource.util.osgi.VersionRange;

import com.springsource.util.osgi.manifest.Resolution;

import ch.mobi.osgi2maven.config.PredefinedDependencies;
import ch.mobi.osgi2maven2.config.MappingConfigParser;
import ch.mobi.osgi2maven2.osgi.OsgiBundle;
import ch.mobi.osgi2maven2.osgi.OsgiResolver;
import ch.mobi.osgi2maven2.osgi.RequiredBundle;
import ch.mobi.osgi2maven2.pom.PomFile;
import ch.mobi.osgi2maven2.pom.PomGenerator;
import ch.mobi.osgi2maven2.script.JarPomPair;
import ch.mobi.osgi2maven2.script.ScriptGenerator;

public class CreatePoms {

	private static final Log logger = LogFactory.getLog();

	public static void main(String argv[]) throws IOException {

		CommandLine cmd = parseCommandLineOptions(argv);

		String[] startPlugins = cmd.getOptionValues('p');
		String pluginDirectoryName = cmd.getOptionValue('d');
		String outputDirectoryName = cmd.getOptionValue('o');
		String mapperConfigFile = cmd.hasOption('m') ? cmd.getOptionValue('m') : "/eclipse-predefined.xml";
		String mavenGroupId = cmd.getOptionValue('g');

		try {
			createPoms(startPlugins, outputDirectoryName, pluginDirectoryName, mapperConfigFile, mavenGroupId);
		} finally {
			LogManager.shutdown();
		}
	}

	@SuppressWarnings("static-access")
	private static CommandLine parseCommandLineOptions(String[] argv) {
		Options options = new Options();

		options.addOption(OptionBuilder.withArgName("output-directory").hasArg().withDescription("Directory where all plugins and generated Artifacts are copied to").isRequired()
				.create('o'));

		options.addOption(OptionBuilder.withArgName("group-id").hasArg().withDescription("groupId for Maven artefacts").isRequired().create('g'));

		options.addOption(OptionBuilder.withArgName("plugin-directory").hasArg().withDescription("Directory containing OSGi plugins").isRequired().create('d'));

		options.addOption(OptionBuilder.withArgName("mapping-file").hasArg().withDescription("Mapper config file").isRequired(false).create('m'));

		options.addOption(OptionBuilder.withArgName("plugin-name").hasArgs().withDescription("Name(s) of the initial plugin(s)").isRequired().create('p'));

		CommandLineParser parser = new PosixParser();

		CommandLine cmd;
		try {

			cmd = parser.parse(options, argv);
		} catch (ParseException e) {

			System.err.println(e.getMessage());
			HelpFormatter helpFormatter = new HelpFormatter();
			helpFormatter.printHelp("osgi2maven2", options);

			System.exit(1);
			throw new RuntimeException("this point is never reached");
		}
		return cmd;
	}

	private static void createPoms(String[] pluginNames, String outputDirectoryName, String pluginDirectoryName, String mapperConfigFile, String mavenGroupId)
			throws FileNotFoundException, IOException {

		logger.debug("startPlugins: %s", Arrays.toString(pluginNames));

		PredefinedDependencies config = MappingConfigParser.getConfig(mapperConfigFile);

		File pluginDirectory = new File(pluginDirectoryName);
		OsgiResolver resolver = new OsgiResolver(pluginDirectory);

		RequiredBundle[] requiredBundles = createRequiredBundles(pluginNames);

		logger.debug("required bundles: %s", Arrays.toString(requiredBundles));

		List<OsgiBundle> allBundles = resolver.transitiveDependencyHull(requiredBundles);

		PomCreator creator = new PomCreator(resolver, config, mavenGroupId);

		List<JarPomPair> pairs = new ArrayList<JarPomPair>();

		for (OsgiBundle bundle : allBundles) {
			PomFile pom = creator.createPom(bundle);
			String pomFileName = bundle.getBundleFileName() + ".pom";
			File pomFile = new File(outputDirectoryName, pomFileName);
			System.out.println("generating: " + pomFileName);
			PomGenerator.generatePom(pomFile, pom);
			bundle.copyJarToDirectory(new File(outputDirectoryName));
			pairs.add(new JarPomPair(bundle.jarFileName(), pomFileName));

		}

		ScriptGenerator.generateInstallScript(new File(outputDirectoryName, "install.sh"), pairs);
		ScriptGenerator.generateDeployScript(new File(outputDirectoryName, "deploy.sh"), pairs);
	}

	private static RequiredBundle[] createRequiredBundles(String[] startPlugins) {
		RequiredBundle requiredBundles[] = new RequiredBundle[startPlugins.length];
		for (int i = 0; i < requiredBundles.length; i++) {
			String symbolicName = startPlugins[i];
			requiredBundles[i] = createWildcardRequiredBundle(symbolicName);
		}
		return requiredBundles;
	}

	static RequiredBundle createWildcardRequiredBundle(String symbolicName) {
		return new RequiredBundle(symbolicName, new VersionRange("0.0.0"));
	}

}
